#ifndef DEBUGOUT_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
	
#define DEBUGOUT_H_INCLUDED
/*
debugout.h
Created: I dunno when by HyperHacker
Version: 1.43
Purpose:
	Debug output wrapper
Runs on: Windows/Linux (include in other apps)

Changes in V1.43 (August 29 2008):
Fixed:
 -Segfault if log file can't be opened.

Changes in V1.42 (June 20 2008):
Fixed:
 -Only use TEXT() if it's defined.

Changes in V1.41 (February 23, 2008):
Fixed:
 -Proper Unicode compatibility using tchar.h.

Changes in V1.4 (February 7, 2008):
Added/Changed:
 -Unicode compatibility.
 -Added DO_FATAL define.

Changes in V1.34 (January 8, 2008):
Added/Changed:
 -Renamed GetErrorMessage to GET_SYSTEM_ERROR_MSG and added 'len' parameter.

Changes in V1.33 (November 12, 2007):
Added/Changed:
 -Added SHOWLINE macro.

Changes in V1.32 (February 3rd 2007):
Fixed:
 -Added DEBUGOUT_CLOSED to prevent destructors from re-opening the debug log
  file after it's been closed, which would result in it not being closed a
  second time (left open at termination).

Changes in V1.31 (December 13 2006):
Fixed:
 -DEBUGOUT_UNLOAD() sets the file pointer to NULL so that if DebugOut() is
  called after this runs (though this shouldn't happen), it won't try to
  write to a closed file.

Changes in V1.3 (October 15 2006):
Added/Changed:
 -Added DEBUGOUT_H_INCLUDED for other files to check for to use DebugOut.
 -Changed changelog format a bit.

Changes in V1.2:
Added/Changed:
 -Printing a message at level DO_NONE in DebugOut() now displays the message
  and closes the program. (Used to display fatal errors.)
 -Added DEBUGOUT_CANCEL_BUTTON.

Changes in V1.1:
Added/Changed:
 -No longer requires debugfile to be defined or closed manually.


Note: To use this you must define the variables ConsoleDebugLevel,
FileDebugLevel and MessageDebugLevel (int).
You may also want to #define DEBUG_FILENAME to set the filename,
else "debug.log" will be used.

WARNING: As of V1.1, debugfile is no longer used. Make sure you are
not still defining and closing this file, or your program will crash!

Template code:
//For DebugOut
int ConsoleDebugLevel = DO_ALL;
int FileDebugLevel = DO_ALL;
int MessageDebugLevel = DO_MAJOR;


If DEBUGOUT_CANCEL_BUTTON is defined, all message boxes displayed by
DebugOut() will have a Cancel button. If this is clicked, the program exits.
This is only intended for cases where the program is already failing, as this
is a 'dirty' exit that won't free allocated memory, close files, etc. If any
additional debug messages appear while the program is closing, be sure to
click OK.

As DebugOut() uses an atexit() handler to close the log file, you should call
it at least once before setting any atexit() handler of your own to ensure
this is the last that gets called, so that the file doesn't get reopened and
never closed by later DebugOut() calls after the handler executes.
*/

//Debug output levels
#ifndef DO_NONE
	#define DO_NONE			0	//No debug output (see below)
	#define DO_CRITICAL		1	//Critical errors (system crash imminent!)
	#define DO_MAJOR		2	//Major errors (uhoh)
	#define DO_MINOR		3	//Minor errors (that doesn't seem right...)
	#define DO_STATUS		4	//Status messages (loading...)
	#define DO_ALL			5	//All messages
	//Note: Using DO_NONE in DebugOut() prints the message and then aborts the
	//program. (Use for fatal errors.)
	#define DO_FATAL		DO_NONE

	//The following are flags that can be passed along with the level;
	//OR the desired level with them to use them.
	#define DO_NO_MSGBOX	0x10 //Don't show message boxes even if enabled
	#define DO_NO_ERROR		0x20 //Don't show last API error
#endif

//Other debug info
#ifndef DO_ERR_THRESHOLD
	#define DO_ERR_THRESHOLD DO_MINOR //Print error message from GetLastError() for levels this and below
#endif

#ifndef DEFAULT_CONSOLE_COLOUR
	#define DEFAULT_CONSOLE_COLOUR 0x1E
#endif

#ifndef DEBUG_FILENAME
	#define DEBUG_FILENAME "debug.log"
#endif

#ifndef GET_SYSTEM_ERROR_MSG
	#define GET_SYSTEM_ERROR_MSG(code, buf, len) FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, code, 0, buf, len, NULL)
#endif

#ifdef TEXT
	#define SHOWLINE DebugOut(DO_ALL, TEXT("%s:%u\n"), __FILE__, __LINE__)
#else
	#define SHOWLINE DebugOut(DO_ALL, "%s:%u\n", __FILE__, __LINE__)
#endif


//Header includes
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#ifndef LINUX
	#include <windows.h>
#endif
#include "tcharx.h"


//Prototypes
void DebugOut(unsigned int Level, const TCHAR *fmt, ...);
void Die(const TCHAR *msg) __attribute__((noreturn));
void DEBUGOUT_UNLOAD();

//Globals
extern unsigned int DebugOut_FileLevel;
extern unsigned int DebugOut_ConsoleLevel;
extern unsigned int DebugOut_MessageLevel;
extern FILE *DEBUGOUT_LOGFILE;
extern bool DEBUGOUT_CLOSED; //if true, the log file was closed, don't re-open it. Prevents destructors from reopening.

#ifdef __cplusplus
}
#endif
#endif //ifdef DEBUGOUT_H_INCLUDED
